Passed
Push — master ( 500eb6...955005 )
by EMP
01:20
created

main.js ➔ setAccountLevel   C

Complexity

Conditions 10

Size

Total Lines 39
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 26
dl 0
loc 39
rs 5.9999
c 0
b 0
f 0
cc 10

How to fix   Complexity   

Complexity

Complex classes like main.js ➔ setAccountLevel often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
"use strict";
2
3
sodium.ready.then(function() {
1 ignored issue
show
Bug introduced by
The variable sodium seems to be never declared. If this is a global, consider adding a /** global: sodium */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
4
5
const ae = new AllEars(function(ok) {
1 ignored issue
show
Bug introduced by
The variable AllEars seems to be never declared. If this is a global, consider adding a /** global: AllEars */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
6
	if (ok) {
7
		document.getElementById("btn_enter").disabled = false;
8
	} else {
9
		console.log("Failed to load All-Ears");
10
	}
11
});
12
13
let page=0;
14
15
function navMenu(num) {
16
	document.getElementById("div_readmsg").hidden = true;
17
18
	const b = document.getElementsByTagName("nav")[0].getElementsByTagName("button");
19
	const d = document.getElementsByClassName("maindiv");
20
21
	for (let i = 0; i < 5; i++) {
22
		if (i === num) {
23
			b[i].disabled = true;
24
			d[i].hidden = false;
25
		} else {
26
			b[i].disabled = false;
27
			d[i].hidden = true;
28
		}
29
	}
30
}
31
32
function getCountryName(countryCode) {
33
	const opts = document.getElementById("gatekeeper_country");
34
35
	for (let i = 0; i < opts.length; i++) {
36
		if (opts[i].value === countryCode) {
37
			return opts[i].textContent;
38
		}
39
	}
40
41
	return "Unknown countrycode: " + countryCode;
42
}
43
44
function getCountryFlag(countryCode) {
45
	const regionalIndicator1 = 127462 + countryCode.codePointAt(0) - 65;
46
	const regionalIndicator2 = 127462 + countryCode.codePointAt(1) - 65;
47
	return "&#" + regionalIndicator1 + ";&#" + regionalIndicator2 + ";";
48
}
49
50
function addMessages() {
51
	const maxExt = ae.GetExtMsgCount();
52
	const maxInt = ae.GetIntMsgCount();
53
54
	let numExt = 0;
55
	let numInt = 0;
56
57
	//TODO handle sent messages separately
58
59
	for (let i = 0; i < (page * 20) + 20; i++) {
60
		const tsInt = (numInt < maxInt) ? ae.GetIntMsgTime(numInt) : 0;
61
		const tsExt = (numExt < maxExt) ? ae.GetExtMsgTime(numExt) : 0;
62
		if (tsInt === 0 && tsExt === 0) break;
63
64
		if (tsInt !== 0 && (tsExt === 0 || tsInt > tsExt)) {
65
			if (i < (page * 20)) {
66
				numInt++;
67
				continue;
68
			}
69
70
			addIntMessage(numInt);
71
			numInt++;
72
		} else if (tsExt !== 0) {
73
			if (i < (page * 20)) {
74
				numExt++;
75
				continue;
76
			}
77
78
			addExtMessage(numExt);
79
			numExt++;
80
		}
81
	}
82
}
83
84
function addExtMessage(i) {
85
	const inbox = document.getElementById("list_inbox");
86
	const sent = document.getElementById("list_sent");
87
88
	const isSent = false;//ae.GetExtMsgIsSent(i);
89
	const elmt = isSent ? sent : inbox;
90
91
	const divTime  = document.createElement("div");
92
	const divSubj  = document.createElement("div");
93
	const divFrom1 = document.createElement("div");
94
	const divFrom2 = document.createElement("div");
95
	const divTo    = document.createElement("div");
96
	const divDel   = document.createElement("div");
97
98
	const ts = ae.GetExtMsgTime(i);
99
	divTime.setAttribute("data-ts", ts);
100
	divTime.textContent = new Date(ts * 1000).toISOString().slice(0, 16).replace("T", " ");
101
	divTime.className = "mono";
102
103
	divSubj.textContent = ae.GetExtMsgTitle(i);
104
105
	const from = ae.GetExtMsgFrom(i);
106
	const from2 = from.substring(from.indexOf("@") + 1);
107
	const cc = ae.GetExtMsgCountry(i);
108
109
	divFrom1.textContent = from.substring(0, from.indexOf("@"));
110
	divFrom2.innerHTML = "<abbr title=\"" + getCountryName(cc) + "\">" + getCountryFlag(cc) + "</abbr>";
111
112
	const fromText = document.createElement("span");
113
	fromText.textContent = " " + from2;
114
	divFrom2.appendChild(fromText);
115
116
	divTo.textContent = ae.GetExtMsgTo(i);
117
	divTo.className = (ae.GetExtMsgTo(i).length === 24) ? "mono" : "";
118
119
	divDel.innerHTML = "<input class=\"delMsg\" type=\"checkbox\" data-id=\"" + ae.GetExtMsgIdHex(i) + "\">";
120
121
	elmt.appendChild(divTime);
122
	elmt.appendChild(divSubj);
123
	elmt.appendChild(divFrom1);
124
	elmt.appendChild(divFrom2);
125
	elmt.appendChild(divTo);
126
	elmt.appendChild(divDel);
127
128
	divSubj.onclick = function() {
129
		navMenu(-1);
130
		document.getElementById("div_readmsg").hidden = false;
131
		document.getElementById("readmsg_head").hidden = false;
132
		document.getElementById("readmsg_levelinfo").hidden = true;
133
		document.getElementById("readmsg_extmsg").hidden = false;
134
		document.getElementById("readmsg_greet").textContent = ae.GetExtMsgGreet(i);
135
		document.getElementById("readmsg_tls").textContent = ae.GetExtMsgTLS(i);
136
		document.getElementById("readmsg_ip").textContent = ae.GetExtMsgIp(i);
137
138
		document.getElementById("readmsg_country").innerHTML = getCountryName(cc) + " " + getCountryFlag(cc);
139
140
		let flagText = "";
141
		if (!ae.GetExtMsgFlagPExt(i)) flagText += "<abbr title=\"The sender did not use the Extended (ESMTP) protocol\">SMTP</abbr> ";
142
		if (!ae.GetExtMsgFlagQuit(i)) flagText += "<abbr title=\"The sender did not issue the required QUIT command\">QUIT</abbr> ";
143
		if (ae.GetExtMsgFlagRare(i)) flagText += "<abbr title=\"The sender issued unusual command(s)\">RARE</abbr> ";
144
		if (ae.GetExtMsgFlagFail(i)) flagText += "<abbr title=\"The sender issued invalid command(s)\">FAIL</abbr> ";
145
		if (ae.GetExtMsgFlagPErr(i)) flagText += "<abbr title=\"The sender violated the protocol\">PROT</abbr> ";
146
		document.getElementById("readmsg_flags").innerHTML = flagText.trim();
147
148
		document.getElementById("readmsg_title").textContent = ae.GetExtMsgTitle(i);
149
		document.getElementById("readmsg_from").textContent = ae.GetExtMsgFrom(i);
150
		document.getElementById("readmsg_to").textContent = ae.GetExtMsgTo(i);
151
		document.getElementById("readmsg_body").textContent = ae.GetExtMsgBody(i);
152
		document.getElementById("readmsg_headers").textContent = ae.GetExtMsgHeaders(i);
153
154
		document.getElementById("readmsg_from").className = "";
155
		document.getElementById("readmsg_to").className = (ae.GetExtMsgTo(i).length === 24) ? "mono" : "";
156
	};
157
158 View Code Duplication
	divDel.children[0].onchange = function() {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
159
		if (!divDel.children[0].checked) {
160
			const checkboxes = elmt.getElementsByTagName("input");
161
			let checked = false;
162
163
			for (let j = 0; j < checkboxes.length; j++) {
164
				if (checkboxes[j].checked) {
165
					checked = true;
166
					break;
167
				}
168
			}
169
170
			if (!checked) {
171
				document.getElementById(isSent ? "btn_sentdel" : "btn_msgdel").hidden = true;
172
				return;
173
			}
174
		}
175
176
		document.getElementById(isSent ? "btn_sentdel" : "btn_msgdel").hidden = false;
177
	};
178
}
179
180
function addIntMessage(i) {
181
	const inbox = document.getElementById("list_inbox");
182
	const sent = document.getElementById("list_sent");
183
184
	const isSent = ae.GetIntMsgIsSent(i);
185
	const elmt = isSent ? sent : inbox;
186
187
	const divTime  = document.createElement("div");
188
	const divSubj  = document.createElement("div");
189
	const divFrom1 = document.createElement("div");
190
	const divFrom2 = document.createElement("div");
191
	const divTo    = document.createElement("div");
192
	const divDel   = document.createElement("div");
193
194
	const ts = ae.GetIntMsgTime(i);
195
	divTime.setAttribute("data-ts", ts);
196
	divTime.textContent = new Date(ts * 1000).toISOString().slice(0, 16).replace("T", " ");
197
	divTime.className = "mono";
198
199
	divSubj.textContent = ae.GetIntMsgTitle(i);
200
201
	divFrom1.textContent = ae.GetIntMsgFrom(i);
202
	divTo.textContent = ae.GetIntMsgTo(i);
203
204
	divTo.className = (ae.GetIntMsgTo(i).length === 24) ? "mono" : "";
205
	divFrom1.className = (ae.GetIntMsgFrom(i).length === 24) ? "mono" : "";
206
207
	divDel.innerHTML = "<input class=\"delMsg\" type=\"checkbox\" data-id=\"" + ae.GetIntMsgIdHex(i) + "\">";
208
209
	elmt.appendChild(divTime);
210
	elmt.appendChild(divSubj);
211
	elmt.appendChild(divFrom1);
212
	if (!isSent) elmt.appendChild(divFrom2);
213
	elmt.appendChild(divTo);
214
	elmt.appendChild(divDel);
215
216
	divSubj.onclick = function() {
217
		navMenu(-1);
218
		document.getElementById("div_readmsg").hidden = false;
219
		document.getElementById("readmsg_head").hidden = false;
220
		document.getElementById("readmsg_levelinfo").hidden = false;
221
		document.getElementById("readmsg_extmsg").hidden = true;
222
223
		document.getElementById("readmsg_title").textContent = ae.GetIntMsgTitle(i);
224
		document.getElementById("readmsg_from").textContent  = ae.GetIntMsgFrom(i);
225
		document.getElementById("readmsg_to").textContent    = ae.GetIntMsgTo(i);
226
		document.getElementById("readmsg_body").textContent  = ae.GetIntMsgBody(i);
227
		document.getElementById("readmsg_level").textContent = ae.GetIntMsgLevel(i);
228
229
		document.getElementById("readmsg_from").className = (ae.GetIntMsgFrom(i).length === 24) ? "mono" : "";
230
		document.getElementById("readmsg_to").className = (ae.GetIntMsgTo(i).length === 24) ? "mono" : "";
231
	};
232
233 View Code Duplication
	divDel.children[0].onchange = function() {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
234
		if (!divDel.children[0].checked) {
235
			const checkboxes = elmt.getElementsByTagName("input");
236
			let checked = false;
237
238
			for (let j = 0; j < checkboxes.length; j++) {
239
				if (checkboxes[j].checked) {
240
					checked = true;
241
					break;
242
				}
243
			}
244
245
			if (!checked) {
246
				document.getElementById(isSent ? "btn_sentdel" : "btn_msgdel").hidden = true;
247
				return;
248
			}
249
		}
250
251
		document.getElementById(isSent? "btn_sentdel" : "btn_msgdel").hidden = false;
252
	};
253
}
254
255
function addFile(num) {
256
	const table = document.getElementById("tbody_filenotes");
257
258
	const row = table.insertRow(-1);
259
	const cellTime = row.insertCell(-1);
260
	const cellSize = row.insertCell(-1);
261
	const cellName = row.insertCell(-1);
262
	const cellBtnD = row.insertCell(-1);
263
	const cellBtnX = row.insertCell(-1);
264
265
	let kib = ae.GetFileSize(num);
266
	if (kib > 1023) kib = Math.round(kib / 1024); else kib = 1;
267
268
	cellTime.textContent = new Date(ae.GetFileTime(num) * 1000).toISOString().slice(0, 16).replace("T", " ");
269
270
	cellSize.textContent = kib;
271
	cellName.textContent = ae.GetFileName(num);
272
	cellBtnD.innerHTML = "<button type=\"button\">D</button>";
273
	cellBtnX.innerHTML = "<button type=\"button\">X</button>";
274
275
	cellBtnD.children[0].onclick = function() {
276
		const parentRow = this.parentElement.parentElement;
277
		const fileBlob = ae.GetFileBlob(parentRow.rowIndex - 1);
278
279
		const a = document.getElementById("a_filedl");
280
		const objectUrl = URL.createObjectURL(fileBlob);
1 ignored issue
show
Bug introduced by
The variable URL seems to be never declared. If this is a global, consider adding a /** global: URL */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
281
		a.href = objectUrl;
282
		a.download = ae.GetFileName(parentRow.rowIndex - 1);
283
		a.click();
284
285
		a.href = "";
286
		a.download = "";
287
		URL.revokeObjectURL(objectUrl);
288
	};
289
290
	cellBtnX.children[0].onclick = function() {
291
		const parentRow = this.parentElement.parentElement;
292
		ae.Message_Delete([ae.GetFileIdHex(parentRow.rowIndex - 1)], function(success) {
293
			if (success) {
294
				table.deleteRow(parentRow.rowIndex - 1);
295
			} else {
296
				console.log("Failed to delete note");
297
			}
298
		});
299
	};
300
}
301
302
function addNote(num) {
303
	const table = document.getElementById("tbody_textnotes");
304
305
	const row = table.insertRow(-1);
306
	const cellTime = row.insertCell(-1);
307
	const cellTitle = row.insertCell(-1);
308
	const cellBtnDe = row.insertCell(-1);
309
310
	cellTime.textContent = new Date(ae.GetNoteTime(num) * 1000).toISOString().slice(0, 16).replace("T", " ");
311
	cellTitle.textContent = ae.GetNoteTitle(num);
312
	cellBtnDe.innerHTML = "<button type=\"button\">X</button>";
313
314
	cellBtnDe.children[0].onclick = function() {
315
		const parentRow = this.parentElement.parentElement;
316
317
		ae.Message_Delete([ae.GetNoteIdHex(parentRow.rowIndex - 1)], function(success) {
318
			if (success) {
319
				table.deleteRow(parentRow.rowIndex - 1);
320
			} else {
321
				console.log("Failed to delete note");
322
			}
323
		});
324
	};
325
326
	cellTitle.onclick = function() {
327
		navMenu(-1);
328
		document.getElementById("div_readmsg").hidden = false;
329
		document.getElementById("readmsg_head").hidden = true;
330
331
		document.getElementById("readmsg_title").textContent = ae.GetNoteTitle(num);
332
		document.getElementById("readmsg_body").textContent = ae.GetNoteBody(num);
333
	};
334
}
335
336
function destroyAccount(upk_hex) {
337
	const tbl = document.getElementById("tbody_admin");
338
339
	let rowid = -1;
340
341
	for (let i = 0; i < tbl.rows.length; i++) {
342
		if (upk_hex === tbl.rows[i].cells[0].textContent) {
343
			rowid = i;
344
			break;
345
		}
346
	}
347
348
	if (rowid === -1) return;
349
350
	ae.Account_Delete(upk_hex, function(success) {
351
		if (success) {
352
			tbl.deleteRow(rowid);
353
		} else {
354
			console.log("Failed to destroy account");
355
		}
356
	});
357
}
358
359
function setAccountLevel(upk_hex, level) {
360
	const tbl = document.getElementById("tbody_admin");
361
362
	let rowid = -1;
363
364
	for (let i = 0; i < tbl.rows.length; i++) {
365
		if (tbl.rows[i].cells[0].textContent === upk_hex) {
366
			rowid = i;
367
			break;
368
		}
369
	}
370
371
	if (rowid === -1) return;
372
373
	ae.Account_Update(upk_hex, level, function(success) {
374
		if (!success) {
375
			console.log("Failed to set account level");
376
			return;
377
		}
378
379
		tbl.rows[rowid].cells[4].textContent = level;
380
381
		if (level === 0) {
382
			tbl.rows[rowid].cells[5].children[0].disabled = false;
383
			tbl.rows[rowid].cells[6].children[0].disabled = true;
384
		} else if (level === ae.GetLevelMax()) {
385
			tbl.rows[rowid].cells[5].children[0].disabled = true;
386
			tbl.rows[rowid].cells[6].children[0].disabled = false;
387
		} else {
388
			tbl.rows[rowid].cells[5].children[0].disabled = false;
389
			tbl.rows[rowid].cells[6].children[0].disabled = false;
390
		}
391
392
		const pkHex = ae.Admin_GetUserPkHex(rowid);
393
		const currentLevel = ae.Admin_GetUserLevel(rowid);
394
		tbl.rows[rowid].cells[5].children[0].onclick = function() {setAccountLevel(pkHex, currentLevel + 1);};
395
		tbl.rows[rowid].cells[6].children[0].onclick = function() {setAccountLevel(pkHex, currentLevel - 1);};
396
	});
397
}
398
399
function deleteAddress(addr) {
400
	let btns = document.getElementById("tbody_opt_addr").getElementsByTagName("button");
401
	for (let i = 0; i < btns.length; i++) btns[i].disabled = true;
402
403
	let addressToDelete = -1;
404
405
	for (let i = 0; i < ae.GetAddressCount(); i++) {
406
		if (addr === ae.GetAddress(i)) {
407
			addressToDelete = i;
408
			break;
409
		}
410
	}
411
412
	if (addressToDelete === -1) return;
413
414
	ae.Address_Delete(addressToDelete, function(success) {
415
		if (success) {
416
			document.getElementById("tbody_opt_addr").deleteRow(addressToDelete);
417
			document.getElementById("send_from").remove(addressToDelete);
418
419
			document.getElementById("addr_use_normal").textContent = ae.GetAddressCountNormal();
420
			document.getElementById("addr_use_shield").textContent = ae.GetAddressCountShield();
421
422
			if (ae.GetAddressCountNormal() < ae.GetAddressLimitNormal(ae.GetUserLevel())) document.getElementById("btn_newaddress").disabled = false;
423
			if (ae.GetAddressCountShield() < ae.GetAddressLimitShield(ae.GetUserLevel())) document.getElementById("btn_newshieldaddress").disabled = false;
424
425
			ae.Private_Update(function(success2) {
426
				if (!success2) console.log("Failed to update the Private field");
427
			});
428
		} else {
429
			console.log("Failed to delete address");
430
		}
431
432
		btns = document.getElementById("tbody_opt_addr").getElementsByTagName("button");
433
		for (let i = 0; i < btns.length; i++) btns[i].disabled = false;
434
	});
435
}
436
437
function shieldMix(addr) {
438
	let newAddr = "";
439
440
	for (let i = 0; i < 24; i++) {
441
		switch (addr.charAt(i)) {
442
			case '1':
443
				newAddr += "1iIlL".charAt(Math.floor(Math.random() * 5));
444
				break;
445
			case '0':
446
				newAddr += "0oO".charAt(Math.floor(Math.random() * 3));
447
				break;
448
			case 'w':
449
				newAddr += "VvWw".charAt(Math.floor(Math.random() * 4));
450
				break;
451
			default:
452
				newAddr += (Math.random() > 0.5) ? addr.charAt(i) : addr.charAt(i).toUpperCase();
453
		}
454
	}
455
456
	return newAddr;
457
}
458
459
function addAddress(num) {
460
	const addrTable = document.getElementById("tbody_opt_addr");
461
	const row = addrTable.insertRow(-1);
462
	const cellAddr = row.insertCell(-1);
463
	const cellChk1 = row.insertCell(-1);
464
	const cellChk2 = row.insertCell(-1);
465
	const cellChk3 = row.insertCell(-1);
466
	const cellBtnD = row.insertCell(-1);
467
468
	cellAddr.textContent = ae.GetAddress(num);
469
	if (cellAddr.textContent.length === 24) cellAddr.className = "mono";
470
	cellAddr.onclick = function() {
471
		if (cellAddr.textContent.length === 24)
472
			navigator.clipboard.writeText(shieldMix(cellAddr.textContent) + "@" + ae.GetDomain());
1 ignored issue
show
Bug introduced by
The variable navigator seems to be never declared. If this is a global, consider adding a /** global: navigator */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
473
		else
474
			navigator.clipboard.writeText(cellAddr.textContent + "@" + ae.GetDomain());
475
	};
476
477
	cellChk1.innerHTML = ae.GetAddressAccExt(num) ? "<input type=\"checkbox\" checked=\"checked\">" : "<input type=\"checkbox\">";
478
	cellChk2.innerHTML = ae.GetAddressAccInt(num) ? "<input type=\"checkbox\" checked=\"checked\">" : "<input type=\"checkbox\">";
479
	cellChk3.innerHTML = ae.GetAddressUse_Gk(num) ? "<input type=\"checkbox\" checked=\"checked\">" : "<input type=\"checkbox\">";
480
481
	cellChk1.onchange = function() {document.getElementById("btn_saveaddrdata").hidden = false;};
482
	cellChk2.onchange = function() {document.getElementById("btn_saveaddrdata").hidden = false;};
483
	cellChk3.onchange = function() {document.getElementById("btn_saveaddrdata").hidden = false;};
484
485
	cellBtnD.innerHTML = "<button type=\"button\">X</button>";
486
	cellBtnD.onclick = function() {deleteAddress(cellAddr.textContent);};
487
488
	const opt = document.createElement("option");
489
	opt.value = cellAddr.textContent;
490
	opt.textContent = cellAddr.textContent + "@" + ae.GetDomain();
491
	document.getElementById("send_from").appendChild(opt);
492
}
493
494
function clearMessages() {
495
	document.getElementById("list_inbox").innerHTML = "<div>Received</div><div>Subject</div><div>Sender</div><div></div><div>Receiver</div><div>Delete</div>";
496
	document.getElementById("list_sent").innerHTML = "<div>Sent</div><div>Subject</div><div>From</div><div>Receiver</div><div>Delete</div>";
497
	document.getElementById("tbody_textnotes").innerHTML = "";
498
	document.getElementById("tbody_filenotes").innerHTML = "";
499
}
500
501
function delMsgs(tblName, btnName) {
502
	const cbs = document.getElementsByClassName("delMsg");
503
	const ids = [];
504
505
	for (let i = 0; i < cbs.length; i++) {
506
		if (cbs[i].checked) ids.push(cbs[i].getAttribute("data-id"));
507
	}
508
509
	if (ids.length > 0) ae.Message_Delete(ids, function(success) {
510
		if (success) {
511
			clearMessages();
512
			addMessages();
513
			document.getElementById(btnName).hidden = true;
514
		} else {
515
			console.log("Failed to delete messages");
516
		}
517
	});
518
}
519
520
function deleteContact(email) {
521
	const tbl = document.getElementById("tbody_notes_contact");
522
	const rows = tbl.rows;
523
524
	for (let i = 0; i < rows.length; i++) {
525
		if (email === rows[i].cells[0].textContent) {
526
			ae.DeleteContact(i);
527
			tbl.deleteRow(i);
528
			break;
529
		}
530
	}
531
532
	document.getElementById("btn_savenotes").hidden = false;
533
}
534
535
function addContactToTable(mail, name, note) {
536
	const contactTable = document.getElementById("tbody_notes_contact");
537
	const row = contactTable.insertRow(-1);
538
	const cellMail = row.insertCell(-1);
539
	const cellName = row.insertCell(-1);
540
	const cellNote = row.insertCell(-1);
541
	const cellBtnD = row.insertCell(-1);
542
543
	cellMail.className = "left";
544
	cellName.className = "left";
545
	cellNote.className = "left";
546
547
	cellMail.textContent = mail;
548
	cellName.textContent = name;
549
	cellNote.textContent = note;
550
	cellBtnD.innerHTML = "<button type=\"button\">X</button>";
551
552
	cellBtnD.onclick = function() {deleteContact(mail);};
553
}
554
555
function addRowAdmin(num) {
556
	const table = document.getElementById("tbody_admin");
557
558
	const row = table.insertRow(-1);
559
	const cellPk = row.insertCell(-1);
560
	const cellMb = row.insertCell(-1);
561
	const cellNa = row.insertCell(-1);
562
	const cellSa = row.insertCell(-1);
563
	const cellLv = row.insertCell(-1);
564
	const cellBtnPl = row.insertCell(-1);
565
	const cellBtnMn = row.insertCell(-1);
566
	const cellBtnDe = row.insertCell(-1);
567
568
	cellPk.textContent = ae.Admin_GetUserPkHex(num);
569
	cellMb.textContent = ae.Admin_GetUserSpace(num);
570
	cellNa.textContent = ae.Admin_GetUserNAddr(num);
571
	cellSa.textContent = ae.Admin_GetUserSAddr(num);
572
	cellLv.textContent = ae.Admin_GetUserLevel(num);
573
	cellBtnPl.innerHTML = "<button type=\"button\">+</button>";
574
	cellBtnMn.innerHTML = "<button type=\"button\">-</button>";
575
	cellBtnDe.innerHTML = "<button type=\"button\">X</button>";
576
577
	cellPk.className = "mono";
578
	if (ae.Admin_GetUserLevel(num) === ae.GetLevelMax()) cellBtnPl.children[0].disabled = true;
579
	if (ae.Admin_GetUserLevel(num) === 0) cellBtnMn.children[0].disabled = true;
580
581
	const pkHex = ae.Admin_GetUserPkHex(num);
582
	const currentLevel = ae.Admin_GetUserLevel(num);
583
	cellBtnPl.children[0].onclick = function() {setAccountLevel(pkHex, currentLevel + 1);};
584
	cellBtnMn.children[0].onclick = function() {setAccountLevel(pkHex, currentLevel - 1);};
585
	cellBtnDe.children[0].onclick = function() {destroyAccount(pkHex);};
586
}
587
588
function addOpt(select, val) {
589
	const opt = document.createElement("option");
590
	opt.value = val;
591
	opt.textContent = val;
592
	select.appendChild(opt);
593
}
594
595
function reloadInterface() {
596
	if (!ae.IsUserAdmin()) document.getElementById("btn_toadmin").hidden = true;
597
	document.getElementById("div_begin").hidden = true;
598
	document.getElementById("div_allears").hidden = false;
599
600
	clearMessages();
601
	document.getElementById("tbody_admin").innerHTML = "";
602
	document.getElementById("tbody_filenotes").innerHTML = "";
603
	document.getElementById("tbody_notes_contact").innerHTML = "";
604
	document.getElementById("tbody_opt_addr").innerHTML = "";
605
	document.getElementById("tbody_textnotes").innerHTML = "";
606
607
	// Contacts
608
	for (let i = 0; i < ae.GetContactCount(); i++) {
609
		addContactToTable(
610
			ae.GetContactMail(i),
611
			ae.GetContactName(i),
612
			ae.GetContactNote(i)
613
		);
614
	}
615
616
	// Addresses
617
	for (let i = 0; i < ae.GetAddressCount(); i++) {
618
		addAddress(i);
619
	}
620
621
	document.getElementById("addr_use_normal").textContent = ae.GetAddressCountNormal();
622
	document.getElementById("addr_use_shield").textContent = ae.GetAddressCountShield();
623
	document.getElementById("addr_max_normal").textContent = ae.GetAddressLimitNormal(ae.GetUserLevel());
624
	document.getElementById("addr_max_shield").textContent = ae.GetAddressLimitShield(ae.GetUserLevel());
625
626
	if (ae.GetAddressCountNormal() >= ae.GetAddressLimitNormal(ae.GetUserLevel())) document.getElementById("btn_newaddress").disabled = true;
627
	if (ae.GetAddressCountShield() >= ae.GetAddressLimitShield(ae.GetUserLevel())) document.getElementById("btn_newshieldaddress").disabled = true;
628
629
	// Gatekeeper data
630
	let gkList = ae.GetGatekeeperAddress();
631
	for (let i = 0; i < gkList.length; i++) addOpt(document.getElementById("gatekeeper_addr"), gkList[i]);
632
633
	gkList = ae.GetGatekeeperDomain();
634
	for (let i = 0; i < gkList.length; i++) addOpt(document.getElementById("gatekeeper_domain"), gkList[i]);
635
636
	let gkCountryCount = 0;
637
	gkList = ae.GetGatekeeperCountry();
638
	for (let i = 0; i < gkList.length; i++) {
639
		const opts = document.getElementById("gatekeeper_country");
640
641
		for (let j = 0; j < opts.length; j++) {
642
			if (opts[j].value === gkList[i]) {
643
				opts[j].selected = "selected";
644
				gkCountryCount++;
645
				break;
646
			}
647
		}
648
	}
649
650
	document.getElementById("gk_countrycount").textContent = gkCountryCount;
651
652
	if (ae.IsUserAdmin()) {
653
		const tblLimits = document.getElementById("tbl_limits");
654
		for (let i = 0; i < 4; i++) {
655
			tblLimits.rows[i].cells[1].children[0].value = ae.GetStorageLimit(i);
656
			tblLimits.rows[i].cells[2].children[0].value = ae.GetAddressLimitNormal(i);
657
			tblLimits.rows[i].cells[3].children[0].value = ae.GetAddressLimitShield(i);
658
		}
659
660
		document.getElementById("btn_admin_savelimits").onclick = function() {
661
			const storageLimit = [];
662
			const addrNrmLimit = [];
663
			const addrShdLimit = [];
664
665
			for (let i = 0; i < 4; i++) {
666
				storageLimit[i] = tblLimits.rows[i].cells[1].children[0].value;
667
				addrNrmLimit[i] = tblLimits.rows[i].cells[2].children[0].value;
668
				addrShdLimit[i] = tblLimits.rows[i].cells[3].children[0].value;
669
			}
670
671
			ae.SetLimits(storageLimit, addrNrmLimit, addrShdLimit, function(success) {
672
				if (!success) {
673
					console.log("Failed to update limits");
674
				}
675
			});
676
		};
677
678
		for (let i = 0; i < ae.Admin_GetUserCount(); i++) {
679
			addRowAdmin(i);
680
		}
681
	}
682
}
683
684
document.getElementById("btn_inbox_prev").onclick = function() {
685
	if (page > 0) {
686
		page--;
687
		clearMessages();
688
		addMessages();
689
		this.disabled = (page === 0);
690
	}
691
};
692
693
document.getElementById("btn_inbox_next").onclick = function() {
694
// TODO: Check if page too high
695
//	if (page > 0) {
696
		page++;
697
		clearMessages();
698
		addMessages();
699
		document.getElementById("btn_inbox_prev").disabled = false;
700
//	}
701
};
702
703
document.getElementById("btn_enter").onclick = function() {
704
	const txtSkey = document.getElementById("txt_skey");
705
	if (!txtSkey.reportValidity()) return;
706
707
	const btn = this;
708
	btn.disabled = true;
709
710
	ae.SetKeys(txtSkey.value, function(successSetKeys) {
711
		if (successSetKeys) {
712
			ae.Account_Browse(0, function(successBrowse) {
713
				if (successBrowse) {
714
					txtSkey.value = "";
715
					reloadInterface();
716
					document.getElementById("btn_refresh").click();
717
				} else {
718
					console.log("Failed to enter");
719
					btn.disabled = false;
720
				}
721
			});
722
		} else {
723
			console.log("Invalid format for key");
724
			btn.disabled = false;
725
		}
726
	});
727
};
728
729
document.getElementById("btn_refresh").onclick = function() {
730
	const btn = this;
731
	btn.disabled = true;
732
733
	ae.Message_Browse(0, function(successBrowse) {
734
		if (successBrowse) {
735
			clearMessages();
736
			addMessages();
737
			for (let i = ae.GetNoteCount() - 1; i >= 0; i--) {addNote(i);}
738
			for (let i = ae.GetFileCount() - 1; i >= 0; i--) {addFile(i);}
739
			btn.disabled = false;
740
		} else {
741
			console.log("Failed to refresh");
742
			document.getElementById("div_begin").hidden = false;
743
			document.getElementById("div_allears").hidden = true;
744
			document.getElementById("btn_enter").disabled = false;
745
			btn.disabled = false;
746
		}
747
	});
748
};
749
750
document.getElementById("btn_contact_add").onclick = function() {
751
	const txtMail = document.getElementById("txt_newcontact_mail");
752
	const txtName = document.getElementById("txt_newcontact_name");
753
	const txtNote = document.getElementById("txt_newcontact_note");
754
755
	addContactToTable(txtMail.value, txtName.value, txtNote.value);
756
	ae.AddContact(txtMail.value, txtName.value, txtNote.value);
757
758
	txtMail.value = "";
759
	txtName.value = "";
760
	txtNote.value = "";
761
762
	document.getElementById("btn_savenotes").hidden = false;
763
};
764
765
document.getElementById("btn_savenotes").onclick = function() {
766
	ae.Private_Update(function(success) {
767
		if (success) {
768
			document.getElementById("btn_savenotes").hidden = true;
769
		} else {
770
			console.log("Failed to save note data");
771
		}
772
	});
773
};
774
775
document.getElementById("btn_msgdel").onclick = function() {
776
	delMsgs("tbody_inbox", "btn_msgdel");
777
};
778
779
document.getElementById("btn_sentdel").onclick = function() {
780
	delMsgs("tbody_sentbox", "btn_sentdel");
781
};
782
783
document.getElementById("btn_send").onclick = function() {
784
	const btn = this;
785
	btn.disabled = true;
786
787
	const scopy = document.getElementById("send_copy");
0 ignored issues
show
Unused Code introduced by
The constant scopy seems to be never used. Consider removing it.
Loading history...
788
	const sfrom = document.getElementById("send_from");
789
	const stitle = document.getElementById("send_title");
790
	const sto = document.getElementById("send_to");
791
	const sbody = document.getElementById("send_body");
792
793
	if (!stitle.reportValidity() || !sto.reportValidity() || !sbody.reportValidity()) return;
794
795
	ae.Address_Lookup(sto.value, function(to_pubkey) {
796
		if (to_pubkey) {
797
			console.log("Lookup ok, trying to send");
798
799
			ae.Message_Create(stitle.value, sbody.value, sfrom.value, sto.value, to_pubkey, function(success) {
800
				if (success) {
801
					stitle.value = "";
802
					sto.value = "";
803
					sbody.value = "";
804
				} else {
805
					console.log("Failed sending message");
806
				}
807
808
				btn.disabled = false;
809
			});
810
		} else {
811
			console.log("Failed looking up address");
812
			btn.disabled = false;
813
		}
814
	});
815
};
816
817
document.getElementById("btn_notenew").onclick = function() {
818
	document.getElementById("div_notes_texts").hidden = true;
819
	document.getElementById("div_newtextnote").hidden = false;
820
};
821
822
document.getElementById("btn_newnote_cancel").onclick = function() {
823
	document.getElementById("txt_newnote_title").value = "";
824
	document.getElementById("txt_newnote_body").value = "";
825
	document.getElementById("div_notes_texts").hidden = false;
826
	document.getElementById("div_newtextnote").hidden = true;
827
};
828
829
document.getElementById("btn_newnote_save").onclick = function() {
830
	const txtTitle = document.getElementById("txt_newnote_title");
831
	const txtBody = document.getElementById("txt_newnote_body");
832
833
	if (!txtTitle.reportValidity() || !txtBody.reportValidity()) return;
834
835
	ae.Message_Assign(false, txtTitle.value, sodium.from_string(txtBody.value), function(success) {
1 ignored issue
show
Bug introduced by
The variable sodium seems to be never declared. If this is a global, consider adding a /** global: sodium */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
836
		if (success) {
837
			addNote(ae.GetNoteCount() - 1);
838
839
			document.getElementById("txt_newnote_title").value = "";
840
			document.getElementById("txt_newnote_body").value = "";
841
			document.getElementById("div_notes_texts").hidden = false;
842
			document.getElementById("div_newtextnote").hidden = true;
843
		} else {
844
			console.log("Failed to save note");
845
		}
846
	});
847
};
848
849
document.getElementById("btn_newaddress").onclick = function() {
850
	if (ae.GetAddressCountNormal() >= ae.GetAddressLimitNormal(ae.GetUserLevel())) return;
851
852
	const txtNewAddr = document.getElementById("txt_newaddress");
853
	if (!txtNewAddr.reportValidity()) return;
854
855
	const btnN = document.getElementById("btn_newaddress");
856
	const btnS = document.getElementById("btn_newshieldaddress");
857
	btnN.disabled = true;
858
	btnS.disabled = true;
859
860
	ae.Address_Create(txtNewAddr.value, function(success1) {
861
		if (success1) {
862
			ae.Private_Update(function(success2) {
863
				document.getElementById("addr_use_normal").textContent = ae.GetAddressCountNormal();
864
				addAddress(ae.GetAddressCount() - 1);
865
				txtNewAddr.value = "";
866
867
				if (!success2) console.log("Failed to update the Private field");
868
869
				if (ae.GetAddressCountNormal() < ae.GetAddressLimitNormal(ae.GetUserLevel())) btnN.disabled = false;
870
				if (ae.GetAddressCountShield() < ae.GetAddressLimitShield(ae.GetUserLevel())) btnS.disabled = false;
871
			});
872
		} else {
873
			console.log("Failed to add address");
874
875
			if (ae.GetAddressCountNormal() < ae.GetAddressLimitNormal(ae.GetUserLevel())) btnN.disabled = false;
876
			if (ae.GetAddressCountShield() < ae.GetAddressLimitShield(ae.GetUserLevel())) btnS.disabled = false;
877
		}
878
	});
879
};
880
881
document.getElementById("btn_newshieldaddress").onclick = function() {
882
	if (ae.GetAddressCountShield() >= ae.GetAddressLimitShield(ae.GetUserLevel())) return;
883
884
	const btnN = document.getElementById("btn_newaddress");
885
	const btnS = document.getElementById("btn_newshieldaddress");
886
	btnN.disabled = true;
887
	btnS.disabled = true;
888
889
	ae.Address_Create("SHIELD", function(success1) {
890
		if (success1) {
891
			ae.Private_Update(function(success2) {
892
				document.getElementById("addr_use_shield").textContent = ae.GetAddressCountShield();
893
				addAddress(ae.GetAddressCount() - 1);
894
895
				if (!success2) console.log("Failed to update the Private field");
896
897
				if (ae.GetAddressCountNormal() < ae.GetAddressLimitNormal(ae.GetUserLevel())) btnN.disabled = false;
898
				if (ae.GetAddressCountShield() < ae.GetAddressLimitShield(ae.GetUserLevel())) btnS.disabled = false;
899
			});
900
		} else {
901
			console.log("Failed to add Shield address");
902
903
			if (ae.GetAddressCountNormal() < ae.GetAddressLimitNormal(ae.GetUserLevel())) btnN.disabled = false;
904
			if (ae.GetAddressCountShield() < ae.GetAddressLimitShield(ae.GetUserLevel())) btnS.disabled = false;
905
		}
906
	});
907
};
908
909
document.getElementById("btn_saveaddrdata").onclick = function() {
910
	const tbl = document.getElementById("tbody_opt_addr");
911
912
	for (let i = 0; i < tbl.rows.length; i++) {
913
		ae.SetAddressAccExt(i, tbl.rows[i].cells[1].firstChild.checked);
914
		ae.SetAddressAccInt(i, tbl.rows[i].cells[2].firstChild.checked);
915
		ae.SetAddressUse_Gk(i, tbl.rows[i].cells[3].firstChild.checked);
916
	}
917
918
	ae.Address_Update(function(success) {
919
		if (success) {
920
			document.getElementById("btn_saveaddrdata").hidden = true;
921
		} else {
922
			console.log("Failed to save address data");
923
		}
924
	});
925
};
926
927
document.getElementById("btn_gkdomain_add").onclick = function() {
928
	const select = document.getElementById("gatekeeper_domain");
929
	const txt = document.getElementById("txt_gkdomain");
930
931
	if (!txt.reportValidity()) return;
932
933
	addOpt(select, txt.value);
934
	txt.value = "";
935
	document.getElementById("btn_savegkdata").hidden = false;
936
};
937
938
document.getElementById("btn_gkaddr_add").onclick = function() {
939
	const select = document.getElementById("gatekeeper_addr");
940
	const txt = document.getElementById("txt_gkaddr");
941
942
	if (!txt.reportValidity()) return;
943
944
	addOpt(select, txt.value);
945
	txt.value = "";
946
	document.getElementById("btn_savegkdata").hidden = false;
947
};
948
949
document.getElementById("btn_gkdomain_del").onclick = function() {
950
	const select = document.getElementById("gatekeeper_domain");
951
	if (select.selectedIndex >= 0) select.remove(select.selectedIndex);
952
	document.getElementById("btn_savegkdata").hidden = false;
953
};
954
955
document.getElementById("btn_gkaddr_del").onclick = function() {
956
	const select = document.getElementById("gatekeeper_addr");
957
	if (select.selectedIndex >= 0) select.remove(select.selectedIndex);
958
	document.getElementById("btn_savegkdata").hidden = false;
959
};
960
961
document.getElementById("btn_savegkdata").onclick = function() {
962
	const blocklist = [];
963
964
	let opts = document.getElementById("gatekeeper_country").selectedOptions;
965
	for (let i = 0; i < opts.length; i++) blocklist.push(opts[i].value);
966
967
	opts = document.getElementById("gatekeeper_domain").options;
968
	for (let i = 0; i < opts.length; i++) blocklist.push(opts[i].value);
969
970
	opts = document.getElementById("gatekeeper_addr").options;
971
	for (let i = 0; i < opts.length; i++) blocklist.push(opts[i].value);
972
973
	ae.SaveGatekeeperData(blocklist, function(success) {
974
		if (success) {
975
			document.getElementById("btn_savegkdata").hidden = true;
976
		} else {
977
			console.log("Failed to update Gatekeeper data");
978
		}
979
	});
980
};
981
982
document.getElementById("btn_admin_addaccount").onclick = function() {
983
	const txtPkey = document.getElementById("txt_newacc_pkey");
984
985
	if (!txtPkey.reportValidity()) return;
986
987
	const btn = document.getElementById("btn_admin_addaccount");
988
	btn.disabled = true;
989
990
	ae.Account_Create(txtPkey.value, function(success) {
991
		if (success) {
992
			addRowAdmin(ae.Admin_GetUserCount() - 1);
993
			txtPkey.value = "";
994
		} else {
995
			console.log("Failed to add account");
996
		}
997
	});
998
999
	btn.disabled = false;
1000
};
1001
1002
document.getElementById("btn_uploadfile").onclick = function() {
1003
	const fileSelector = document.getElementById("upfile");
1004
	const f = fileSelector.files[0];
1005
1006
	if (f.name.length + f.size > 8138) {
1007
		console.log("Too large");
1008
		fileSelector.value = null;
1009
		return;
1010
	}
1011
1012
	const btn = this;
1013
	btn.disabled = true;
1014
1015
	const reader = new FileReader();
1 ignored issue
show
Bug introduced by
The variable FileReader seems to be never declared. If this is a global, consider adding a /** global: FileReader */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
1016
	reader.onload = function(e) {
0 ignored issues
show
Unused Code introduced by
The parameter e is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1017
		const u8data = new Uint8Array(reader.result);
1018
1019
		ae.Message_Assign(true, f.name, u8data, function(success) {
1020
			if (success) {
1021
				addFile(ae.GetFileCount() - 1);
1022
				fileSelector.value = null;
1023
			} else {
1024
				console.log("Failed to upload file");
1025
			}
1026
1027
			btn.disabled = false;
1028
		});
1029
	};
1030
1031
	reader.readAsArrayBuffer(f);
1032
};
1033
1034
function navNotesMenu(num) {
1035
	document.getElementById("div_newtextnote").hidden = true;
1036
1037
	for (let i = 0; i < 4; i++) {
1038
		if (i === num) {
1039
			document.getElementById("div_notes").children[0].children[i].disabled = true;
1040
			document.getElementById("div_notes").children[1 + i].hidden = false;
1041
		} else {
1042
			document.getElementById("div_notes").children[0].children[i].disabled = false;
1043
			document.getElementById("div_notes").children[1 + i].hidden = true;
1044
		}
1045
	}
1046
}
1047
1048
document.getElementById("btn_prefs_gatekeeper").onclick = function() {
1049
	document.getElementById("btn_prefs_addresses").disabled = false;
1050
	document.getElementById("btn_prefs_gatekeeper").disabled = true;
1051
	document.getElementById("div_prefs_gatekeeper").hidden = false;
1052
	document.getElementById("div_prefs_addresses").hidden = true;
1053
1054
	document.getElementById("div_prefs_gatekeeper").style.width = getComputedStyle(document.getElementById("gatekeeper_country")).width;
1055
};
1056
1057
document.getElementById("btn_prefs_addresses").onclick = function() {
1058
	document.getElementById("btn_prefs_addresses").disabled = true;
1059
	document.getElementById("btn_prefs_gatekeeper").disabled = false;
1060
	document.getElementById("div_prefs_gatekeeper").hidden = true;
1061
	document.getElementById("div_prefs_addresses").hidden = false;
1062
};
1063
1064
let btns = document.getElementsByTagName("nav")[0].getElementsByTagName("button");
1065
btns[0].onclick = function() {navMenu(0);};
1066
btns[1].onclick = function() {navMenu(1);};
1067
btns[2].onclick = function() {navMenu(2);};
1068
btns[3].onclick = function() {navMenu(3);};
1069
btns[4].onclick = function() {navMenu(4);};
1070
1071
btns = document.getElementById("div_notes").getElementsByTagName("button");
1072
btns[0].onclick = function() {navNotesMenu(0);};
1073
btns[1].onclick = function() {navNotesMenu(1);};
1074
btns[2].onclick = function() {navNotesMenu(2);};
1075
btns[3].onclick = function() {navNotesMenu(3);};
1076
1077
document.getElementById("gatekeeper_country").onchange = function() {
1078
	document.getElementById("btn_savegkdata").hidden = false;
1079
};
1080
1081
document.getElementById("txt_skey").onkeyup = function(e) {
1082
	if (e.key === "Enter") document.getElementById("btn_enter").click();
1083
};
1084
1085
navMenu(0);
1086
1087
});
1088